/**
* Copyright 2013 nabla
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package com.nabla.wapp.report.client.ui;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import com.nabla.wapp.client.general.Application;
import com.nabla.wapp.client.general.LoggerFactory;
import com.nabla.wapp.client.model.AsyncGetDefaultValuesCallback;
import com.nabla.wapp.client.mvp.IWizardPageDisplay;
import com.nabla.wapp.client.mvp.binder.BindedWizardPageDisplay;
import com.nabla.wapp.client.ui.WizardPage;
import com.nabla.wapp.client.ui.WizardPageNavigations;
import com.nabla.wapp.client.ui.form.Form;
import com.nabla.wapp.report.client.model.ParameterModel;
import com.nabla.wapp.report.client.parameter.ParameterBinderList;
import com.nabla.wapp.report.shared.IReport;
import com.nabla.wapp.report.shared.parameter.ParameterGroup;
import com.nabla.wapp.report.shared.parameter.ParameterValueList;
import com.nabla.wapp.shared.command.GetFormDefaultValues;
import com.nabla.wapp.shared.general.StringSet;
import com.nabla.wapp.shared.slot.ISlot;
import com.nabla.wapp.shared.slot.ISlot1;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;


public class ParameterWizardPageUi extends BindedWizardPageDisplay<WizardPage> implements IWizardPageDisplay {

	private static final Logger			log = LoggerFactory.getLog(ParameterWizardPageUi.class);
	private final Form 					form = new Form();
	private final ParameterBinderList		binders;
    private final ISlot                 onNextHandler;

	public ParameterWizardPageUi(final ParameterGroup reportParameters, final ParameterValueList values, final WizardPageNavigations nextButton, final ISlot onNextHandler) {
		super(nextButton);
        this.onNextHandler = onNextHandler;
		binders = new ParameterBinderList(reportParameters, values);
		form.setModel(new ParameterModel(binders));
		binders.createFormItem(form);
		impl = new WizardPage();
		impl.setTitle(reportParameters.getPrompt());
		impl.add(form);
        final StringSet parameterNames = new StringSet();
        reportParameters.addNameToSet(parameterNames);
		final Set<String> readyParameters = new HashSet<String>(parameterNames);
		log.fine("binding form items and waiting for readyness of " + readyParameters);
    	binders.bind(form, new ISlot1<String>() {

			@Override
			public void invoke(String parameterName) {
				if (!readyParameters.isEmpty()) {
					log.fine("parameter '" + parameterName + "' is ready");
					readyParameters.remove(parameterName);
					if (readyParameters.isEmpty()) {
						log.fine("editing form with default parameter values");
						editNewRecordWithDefault(parameterNames);
					}
				}
			}

    	});
	}

	@Override
	public boolean validate() {
		return form.validate();
	}

	@Override
	public boolean hasErrors() {
		return form.hasErrors();
	}

	public void storeValues() {
		binders.storeValue(form);
	}

	private void editNewRecordWithDefault(final StringSet parameterNames) {
		Application.getInstance().getDispatcher().execute(new GetFormDefaultValues(IReport.PRINT_REPORT_PREFERENCE_GROUP, parameterNames), new AsyncGetDefaultValuesCallback() {
			@Override
			public void onFailure(@SuppressWarnings("unused") final Throwable caught) {
				onDefaultValuesArrived(parameterNames, null);
			}

			@Override
			public void onDefaultValues(final Map values) {
                onDefaultValuesArrived(parameterNames, values);
			}
		});
	}

    private void onDefaultValuesArrived(final Set<String> parameterNames, final Map values) {
		if (values != null)
			form.editNewRecord(values);
		else
			form.editNewRecord();
		for (String parameter : parameterNames)
            ChangedEvent.fire(form.getItem(parameter), null);
    }

	@Override
	public void onNextClicked() {
		storeValues();
        onNextHandler.invoke();
	}
}
